chore: add telemetry to setup script MCP-460#1085
Conversation
Made-with: Cursor # Conflicts: # src/telemetry/telemetry.ts # src/web.ts
There was a problem hiding this comment.
Pull request overview
This PR introduces telemetry for the interactive setup wizard and refactors the telemetry pipeline to be configurable without requiring a full Session, improving reuse across setup/runtime and updating tests and public API reports accordingly.
Changes:
- Add
SetupTelemetryto emit structured, step-based setup events (with stablesetup_session_idand accumulated context). - Refactor
Telemetry.createto support a newTelemetryConfigobject (keeping the legacy overload deprecated) and update call sites/tests. - Improve secret redaction in setup error formatting by redacting against globally-registered secrets.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/telemetry.test.ts | Updates unit tests to use TelemetryConfig-based construction and host-supplied common properties. |
| tests/unit/setup/setupTelemetry.test.ts | Adds unit coverage for the new SetupTelemetry event semantics and flush behavior. |
| tests/unit/resources/common/debug.test.ts | Updates test wiring to new Telemetry.create({ ... }) signature. |
| tests/integration/ui/mcpUIFeature.test.ts | Updates telemetry wiring for integration test server/session setup. |
| tests/integration/tools/mongodb/mongodbTool.test.ts | Updates telemetry wiring for tool integration tests. |
| tests/integration/telemetry.test.ts | Simplifies integration test by constructing telemetry directly from config. |
| tests/integration/server.test.ts | Updates server integration test telemetry wiring to new constructor. |
| tests/integration/helpers.ts | Updates shared integration test harness to construct telemetry via TelemetryConfig. |
| src/web.ts | Updates public exports to include TelemetryConfig as a type export. |
| src/transports/base.ts | Switches transport runner telemetry initialization to TelemetryConfig with dynamic getCommonProperties(). |
| src/telemetry/types.ts | Adds setup telemetry types (SetupCommand, SetupEventProperties, SetupEvent). |
| src/telemetry/telemetry.ts | Introduces TelemetryConfig, adds new create(config) overload, and deprecates legacy overload. |
| src/setup/setupTelemetry.ts | Adds the SetupTelemetry implementation and helpers (context accumulation, step durations, terminal events). |
| src/setup/setupMcpServer.ts | Wires setup wizard steps to SetupTelemetry and adds redaction registration for setup secrets. |
| src/setup/setupAiToolsUtils.ts | Redacts formatted error messages using globally-registered secrets. |
| src/lib.ts | Exports TelemetryConfig type from the package entrypoint. |
| src/index.ts | Simplifies setup execution path to call runSetup(config) directly. |
| src/common/session.ts | Makes Session.logger readonly (reflected in API reports). |
| api-extractor/reports/web.public.api.md | Updates public API report for telemetry overloads and new TelemetryConfig. |
| api-extractor/reports/mongodb-mcp-server.public.api.md | Updates public API report for telemetry overloads and new TelemetryConfig. |
Comments suppressed due to low confidence (1)
src/telemetry/telemetry.ts:158
- In the
Telemetry.create(...)implementation, the destructured parameter defaulteventCache = EventCache.getInstance()is evaluated even when callers use the newTelemetryConfigoverload (because the parameter is always destructured). This adds an unnecessary side effect/overhead and makesEventCache.getInstanceharder to reason about in tests. Consider only resolving the legacy defaults when the legacy overload is actually used (e.g., branch onuserConfig/deviceIdbefore applying defaults).
{
commonProperties = {},
eventCache = EventCache.getInstance(),
}: {
commonProperties?: Partial<CommonProperties>;
Coverage Report for CI Build 24830273274Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage decreased (-0.03%) to 81.594%Details
Uncovered Changes
Coverage Regressions2 previously-covered lines in 1 file lost coverage.
Coverage Stats💛 - Coveralls |
| browser: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodString]>>; | ||
| }, z.core.$strip>; | ||
|
|
||
| // Warnings were encountered during analysis: |
There was a problem hiding this comment.
should this file be added to prettier ignore? is this why this is reformatted?
There was a problem hiding this comment.
No idea what caused this reformat 😬 It looks like it's already ignored.
There was a problem hiding this comment.
Actually, as far as I can tell, it was formatted according to the prettier rules. The current version is regenerated and not prettier-formatted, which seems to be causing the difference.
| command: "completed", | ||
| ai_tool: "claudeDesktop", | ||
| is_read_only: "false", | ||
| has_docker: "false", |
There was a problem hiding this comment.
we should use the same structure where possible so this should be is_container_env
| expect(completed.properties).toMatchObject({ | ||
| command: "completed", | ||
| ai_tool: "claudeDesktop", | ||
| is_read_only: "false", |
There was a problem hiding this comment.
this should be read_only_mode
|
|
||
| const completed = mock.emitted.at(-1)!; | ||
| expect(completed.properties).toMatchObject({ | ||
| command: "completed", |
There was a problem hiding this comment.
nit: we don't need to use command to define this sort of events - we should design the events to fit the scenario you are tracking here - I think this warrants a discussion w/ Analytics about the expected shape for the events
There was a problem hiding this comment.
a better design would be to create a command setup and then you can define the states as a stage or status property
| has_docker?: TelemetryBoolSet; | ||
|
|
||
| /** Whether the current OS/architecture is supported by the MCP server. */ | ||
| platform_supported?: TelemetryBoolSet; |
There was a problem hiding this comment.
why not send the platform value as well? platform is the value, and we have that in telemetry too
| node_version_ok?: TelemetryBoolSet; | ||
|
|
||
| /** Whether the user supplied a MongoDB connection string. */ | ||
| connection_string_provided?: TelemetryBoolSet; |
There was a problem hiding this comment.
| connection_string_provided?: TelemetryBoolSet; | |
| config_connection_string?: TelemetryBoolSet; |
| * accumulated context known up to that point so each event is independently | ||
| * queryable. | ||
| */ | ||
| export type SetupEventProperties = { |
There was a problem hiding this comment.
I left a few in-line comments, but overall I suggest that we reuse the properties where possible, I don't think it makes sense and add new ones where needed, right?
There was a problem hiding this comment.
you can probably reuse the commonBaseProperties and extract the common properties that you want to capture in the events here
| deviceId: this.deviceId, | ||
| apiClient: session.apiClient, | ||
| keychain: session.keychain, | ||
| enabled: userConfig.telemetry !== "disabled", |
There was a problem hiding this comment.
nit: I'd instead validate it is equal to enabled
Proposed changes
Adds setup telemetry. Additionally, modifies the telemetry service constructor to decouple it from the session and userConfig objects. Backwards compatibility is preserved by adding an overload for
Telemetry.create.Telemetry events for the setup script are emitted at every step indicating success/failure while ensuring we don't leak any PII.